home *** CD-ROM | disk | FTP | other *** search
- // ARELYS.CPP - A robot "driver" for RARS, by M. Timin, February, 1995
- // ver. 0.39 3/6/95
-
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "car.h"
-
- const double CORN_SPD_CON = 5.7; // determines how fast to take corners
- const double BIAS = 0.05; // estimate of alpha when cornering
- const double STEER_GAIN = 0.7; // servo gain, for staying in "lane"
- const double STEER_DAMP = 2.0; // servo damping, to prevent "weaving"
- const double SLIP_LIM = 4.0; // maximum wheel slip, ft/sec, in wheel_slip()
- const double SLIP_CON = 199.0; //
- const double SHARP_TURN = .1; // change in alpha when attempting to pass
- const int PASSING_TIME = 70; // time to stay in passing maneuver, counts
- const double CUSHION = 10.0; // feet from inside rail to shoot for
- const double CRIT_WIDTHS = 2.9; // length in widths meaning nearing corner
- const double BRAK_ACCEL = 23.0; // braking acceleration, ft/sec sq.
-
- extern char* glob_name; // The name string, below, will be copied here
-
- double sdc(double radius)
- {
- if(radius < 0.0) // change sign of negative radius
- radius = -radius;
- else if(radius == 0.0) // This is just insurance, this funtion doesn't
- return(200.0); // make sense when the radius is zero.
- return CORN_SPD_CON * sqrt(radius);
- }
-
- double sdw(double goal, double present)
- {
- double ws;
-
- if(present > goal + 2 * SLIP_LIM) // if too fast,
- ws = present - SLIP_LIM; // slow down.
- else if(present < goal - 2 * SLIP_LIM) // if too slow,
- ws = present + SLIP_LIM; // accelerate.
- else // if quite close,
- ws = (goal + present) / 2; // approach desired speed gently.
-
- if(ws < present) // can slip more when braking
- ws -= (present - ws);
-
- return ws;
- }
-
- double widths(double len, double rad, double wide)
- {
- if(rad == 0.0)
- return len/wide;
- else if(rad > 0.0)
- return (rad+.5*wide)*len/wide;
- else
- return (.5*wide - rad)*len/wide;
- }
-
- con_vec arelys(situation s)
- {
- const char name[] = "Arelys"; // This is the robot driver's name!
- static int init_flag = 1; // cleared by first call
- double speed; // target speed for cornering, ft/sec
- double speed_next; // target speed for next corner
- con_vec result; // This is what is returned.
- double width; // track width, feet
- double alpha, vc; // components of result
- static double alpha_inc = 0.0; // alpha increment during passing maneuver
- static int counting = 0; // will be set and counting down when passing
- double dest; // target distance from left wall
- double arg; // for temporary storage of calculation
- double widths_cur; // length remaining of current segment, widths
- static int started = 0; // set after the "dragout"
- double redline; // speed at which to begin braking on straight
- double bias; // estimated alpha value for a curve
-
- if(init_flag) { // first time through, only copy name:
- strcpy(glob_name, name);
- init_flag = 0;
- result.alpha = result.vc = 0;
- return result;
- }
-
- if(stuck(s.backward, s.v,s.vn, s.to_lft,s.to_rgt, &result.alpha,&result.vc))
- return result;
-
- width = s.to_lft + s.to_rgt;
- widths_cur = widths(s.to_end, s.cur_rad, width);
- // widths_nex = widths(s.nex_len, s.nex_rad, width);
-
- if(s.cur_rad == 0.0)
- if(s.nex_rad > 0.0)
- dest = 2.0 * CUSHION;
- else
- dest = width - 2.0 * CUSHION;
- else if(s.cur_rad > 0.0)
- if(s.nex_rad >= 0.0)
- dest = CUSHION;
- else if(widths_cur > CRIT_WIDTHS)
- dest = CUSHION;
- else
- dest = .5 * width;
- else
- if(s.nex_rad <= 0.0)
- dest = width - CUSHION;
- else if(widths_cur > CRIT_WIDTHS)
- dest = width - CUSHION;
- else
- dest = .5 * width;
-
- // calculate target speeds for current corner and the next:
- if(s.cur_rad == 0.0)
- arg = 0.0;
- else if(s.cur_rad > 0.0)
- arg = s.cur_rad + .5 * width;
- else
- arg = s.cur_rad - .5 * width;
- speed = sdc(arg); // speed is based on radius
-
- if(s.cur_rad == 0.0) // calculate a bias for alpha in a turn:
- bias = 0.0;
- else if(s.cur_rad > 0.0)
- bias = 100 * BIAS / speed;
- else
- bias = -100.0 * BIAS / speed;
-
- if(s.nex_rad == 0.0) // calculate speed for next turn
- arg = 0.0;
- else if(s.nex_rad > 0.0)
- arg = s.nex_rad + .5 * width;
- else
- arg = s.nex_rad - .5 * width;
- speed_next = sdc(arg); // of center line of track.
-
- alpha = bias + STEER_GAIN * (s.to_lft - dest) / width;
- alpha -= STEER_DAMP * s.vn / s.v; // This is damping, to prevent oscillation
-
- // now set the tire speed, vc:
- if(s.cur_rad == 0.0) { // If we are on a straightaway,
- redline = sqrt(speed_next * speed_next + BRAK_ACCEL * 2.0 * s.to_end);
- if(s.v > .85 * redline)
- started = 1;
- if(s.v < redline)
- vc = s.v + SLIP_CON / s.v; // keep accellerating near full power
- else // otherwise,
- vc = sdw(speed_next, s.v); // brake for next corner
- }
- else // If we're in the curve, maintain speed.
- if(widths_cur > CRIT_WIDTHS)
- // if we are far from the next corner, stay at "speed".
- vc = sdw(speed, s.v);
- else // but when we near the next corner, adjust to "speed_next"
- vc = sdw(speed_next, s.v);
- if(!started) // don't steer during dragout
- if(s.vn > .02 * s.v || s.vn < -.02 * s.v) // except if astray
- started = 1;
- else
- alpha = 0;
- // The passing maneuver:
- if(s.dead_ahead & !counting) { // When first encountering the car ahead:
- counting = PASSING_TIME; // setup the timer,
- if(random(29999) < 15000) // choose a right or left maneuver:
- alpha_inc = SHARP_TURN;
- else
- alpha_inc = -SHARP_TURN;
- }
- if(counting) { // If we are still in the passing maneuver,
- alpha += alpha_inc; // change alpha
- --counting; // count down to zero
- }
-
- result.vc = vc; result.alpha = alpha;
- return result;
- }
-